#pragma once
#include "stdafx.h"
#include "Ar.h"
#include "Model.h"

Model :: Model(int length)
{
	context_length = length;
	first = new Context_model (0);
}

Link * Model :: Encode_sym(int sym, int *context)
{
	int success = 0;
	int i = 1;
	Context_model *cur = first;
	Link *match = NULL, *pred;
	while (match == NULL)
	{
		match = cur->Encode_sym(sym, context);
		cur = cur->GetNext();
	}
	pred = match;
	while ((success == 0) && (pred != NULL))
	{
		success = encode_symbol(pred, sym);
		pred = pred->GetPred();
	}
	return match;
}

Link * Model :: Decode(int *context, int &c)
{
	int success = 0;
	Context_model *cur = first;
	Link *match = NULL, *pred;
	while (match == NULL)
	{
		match = cur->Decode(context);
		cur = cur->GetNext();
	}
	pred = match;
	while ((pred != NULL) && (success == 0))
	{
		c = decode_symbol(pred);
		pred = pred->GetPred();
		if (c != 256)
			success = 1;
	}
	return match;
}

void Model :: Update(int sym, int *context, Link *match)
{
	int k = -1;
	Context_model *cur = first;
	Link *pred = match;
	while ((context[k+1] != '\0') && (k < context_length))
		k++;
	while (cur->GetSize() > match->GetLength())
	{
		cur = cur->GetNext();
	}
	while (cur != NULL)
	{
		cur->Update(sym, context, pred);
		cur = cur->GetNext();
		pred = pred ->GetPred();
	}
	cur = first;
	pred = match;
	while (cur->GetSize() > pred->GetLength())
	{
		while ((cur->GetSize() - pred->GetLength()) != 1)
				cur = cur->GetNext();
		pred = cur->Update(sym, context, pred);
		cur = first;
	}
	if (k > first->GetSize())
	{
		Context_model *next = new Context_model (k, first, context, pred);
		first = next;
	}
}

Model :: ~Model()
{
	Context_model * cur = first, *next;
	while (cur != NULL)
	{
		next = cur->GetNext();
		delete cur;
		cur = next;
	}
}